package uk.co.douglashoskins.weathercompare.providers;

import java.io.DataInputStream;
import java.io.IOException;

import javax.microedition.lcdui.Image;

import org.json.me.JSONArray;
import org.json.me.JSONException;
import org.json.me.JSONObject;

import uk.co.douglashoskins.weathercompare.Assets;
import uk.co.douglashoskins.weathercompare.WeatherCompare;
import uk.co.douglashoskins.weathercompare.controller.WeatherObj;
import uk.co.douglashoskins.weathercompare.services.NetQueueCallback;
import uk.co.douglashoskins.weathercompare.util.URLEncoder;
import uk.co.douglashoskins.weathercompare.util.Weather;

public class YrNo implements NetQueueCallback, WeatherProvider {

	private int translateCode(int code) {
		switch (code) {
			case 15:
				return Weather.FOG;
			case 6:
			case 11:
			case 14:
				return Weather.THUNDERSTORM;
			
			case 7:
			case 8:
			case 12:
			case 13:
				return Weather.SNOW;
			
			case 5:
			case 9:
			case 10:
				return Weather.RAIN;
			
			case 2:
			case 3:
				return Weather.SUNNY_INTERVALS;
				
			case 1: return Weather.SUN;
		}
		return Weather.CLOUD;
	}
	
	public void netCallback(String s) throws IOException {
		try {
			JSONObject j = new JSONObject(s);
			JSONObject results = j.getJSONObject("query").getJSONObject("results");
			JSONArray times = results.getJSONObject("weatherdata").getJSONObject("forecast").getJSONObject("tabular").getJSONArray("time");
			int numTimes = times.length();
			String today = null, tomorrow = null;
			WeatherObj wo = new WeatherObj();
			wo.today.high = Integer.MIN_VALUE;
			wo.today.low = Integer.MAX_VALUE;
			wo.tomorrow.high = Integer.MIN_VALUE;
			wo.tomorrow.low = Integer.MAX_VALUE;
			for (int i=0; i<numTimes; i++) {
				JSONObject time = times.getJSONObject(i);
				String from = time.getString("from");
				int temp = time.getJSONObject("temperature").getInt("value");
				JSONObject symbol = time.getJSONObject("symbol");
				String symbolText = symbol.getString("name");
				int symbolNum = symbol.getInt("number");
				if (today == null) {
					today = from.substring(0, 10);
					wo.today.text = symbolText;
					wo.today.code = translateCode(symbolNum);
				} 
				if (from.startsWith(today)) {
					if (temp < wo.today.low) { wo.today.low = temp; }
					if (temp > wo.today.high) { wo.today.high = temp; }
				} else {
					if (tomorrow == null) {
						tomorrow = from.substring(0, 10);
						wo.tomorrow.text = symbolText;
						wo.tomorrow.code = translateCode(symbolNum);
					}
					if (from.startsWith(tomorrow)) {
						if (temp < wo.tomorrow.low) { wo.tomorrow.low = temp; }
						if (temp > wo.tomorrow.high) { wo.tomorrow.high = temp; }
					} else {
						break;
					}
				}
			}
			
			wc.weatherCB(wo, this);
			j = null;
			System.gc();
		} catch (JSONException e) {
			wc.weatherErr(this);
		}
	}

	public void netException(Exception exc) {
		wc.weatherErr(this);
	}
	
	private int closest(DataInputStream dis, double lat, double lng) throws IOException {
		int num = dis.readInt();
		int closest=0;
		double min = Double.MAX_VALUE;
		for (int i=0; i<num; i++) {
			double lat1 = dis.readDouble();
			double lng1 = dis.readDouble();
			double dist = Weather.haversine(lat, lng, lat1, lng1);
			if (dist < min) {
				min = dist;
				closest = i;
			}
		}
		
		return closest;
	}
	private WeatherCallback wc;
	public void getWeather(double lat, double lng, WeatherCallback wc) {
		// YR.NO data is 40 files of 153s entries.
		// Load the lats and lons
		this.wc = wc;
		try {
			DataInputStream dis = new DataInputStream(this.getClass().getResourceAsStream("res/data/yrno_coords.txt"));
			int closest = closest(dis, lat, lng);
			dis.close();
			
			int file = closest / 153;
			int entry = closest % 153;
			dis = new DataInputStream(this.getClass().getResourceAsStream("res/data/yrno_" + file + ".txt"));
			String xml = null;
			for (int i=0; i<entry; i++) {
				xml = dis.readUTF();
			}
			dis.close();
			String urlEncoded = URLEncoder.encode(xml);
			String yql = "http://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20xml%20where%20url%20%3D%20%22" + urlEncoded + "%22&format=json";
			WeatherCompare.n.addRequest(yql, this);
		} catch (IOException e) {
			e.printStackTrace();
		}
		
	}

	public Image logo() { return Assets.YRNO; }

	public String name() { return "YrNo"; }
}
